#include "notify_presence_task.h"

#include "base/logging.h"
#include "im/adapters/session_adapter.h"
#include "im/adapters/recent_contact_adapter.h"
#include "im/adapters/message_outlet_adapter.h"

namespace imserver {

int GetOnlineRecentContacts(int64_t uid, std::vector<int64_t> * online_contacts) {
  RecentContactList recent_list;
  if (RecentContactAdapter::Instance().GetContacts(uid, 0, 50, &recent_list, 2) != 0) {
    LOG_WARN("GetOnlineRecentContacts GetContacts err, uid=" << uid);
    return -1;
  }

  std::vector<int64_t> recent_ids;
  for(size_t i = 0; i < recent_list.size(); ++i) {
    recent_ids.push_back(recent_list[i].uid);
  }

  std::map<int64_t, SessionType::type> online_map;
  if (SessionAdapter::Instance().GetOnlineUsers(recent_ids, &online_map)) {
    LOG_WARN("GetOnlineRecentContacts GetOnlineUsers err, uid=" << uid);
    return -2;
  }

  const size_t MAX_PUSH = 15; // 是个约数
  for(std::map<int64_t, SessionType::type>::iterator it = online_map.begin(); it != online_map.end(); ++it) {
    if ((rand() % online_map.size()) > MAX_PUSH) {
      continue;
    }
    online_contacts->push_back(it->first);
  }
  LOG_INFO("GetOnlineRecentContacts uid=" << uid << " size=" << online_contacts->size());
  return 0;
}

const char * SessionTypeName(int type);

void NotifyPresenceTask::run() {
  SessionList uid_sessions;
  SessionAdapter::Instance().GetSessionList(uid_, &uid_sessions, 2);
  if (uid_sessions.size() > 1) {
    LOG_INFO("NotifyPresenceTask::run() multi session, uid=" << uid_ << " session=" << session_ << " type=" << type_);
    return;
  }
  if (uid_sessions.size() == 1) {
    if (uid_sessions[0].key != session_) {
      LOG_INFO("NotifyPresenceTask::run() other session exist, uid=" << uid_ << " session=" << session_ << " type=" << type_);
      return;
    }
  }

  LOG_INFO("NotifyPresenceTask::run() notify presence, uid=" << uid_ << " session=" << session_ << " type=" << type_);

  ImMessage presence_message;
  presence_message.sender = uid_;
  presence_message.timestamp = time(NULL);

  SetMessageType(presence_message, MSG_TYPE_PRESENCE);

  std::vector<int64_t> online_contacts;
  int r = GetOnlineRecentContacts(uid_, &online_contacts);
  if (r != 0 || online_contacts.empty()) {
    return; 
  }
  for(size_t i = 0; i < online_contacts.size(); ++i) {
    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(online_contacts[i], &sessions, 2);

    presence_message.body = SessionTypeName(type_); // == SessionType::OFFLINE ? "OFFLINE" : "WEB");

    for(size_t j = 0; j < sessions.size(); ++j) {
      presence_message.receiver = online_contacts[i];
      int res = MessageOutletAdapter::Instance().DistributeMessage(sessions[j].key, presence_message, 2);
      if (res == 0) {
        LOG_INFO("MessageOutletAdapter send presence message ok.");
      } else {
        LOG_WARN("MessageOutletAdapter send presence message err.");
      }
    }
  }
}

}


